/*
   This class can be inherited from to create forms as widgets that do not send form POST data - but rather, perform custom actions.
   It is up to the child of this class to emit the formExecuted notification - putting this in a DialogForm will not function correctly.
   
   Please remember to add any widgets you want validated to this.mChildWidgets.
*/
define(
   [
      'dojo/_base/declare',
	   'dojo/_base/array', // array.every array.filter array.forEach array.indexOf array.map
      'dojo/_base/lang',
      'noBusinessBase/widgets/ButtonRow',
      'noBusinessBase/form/WidgetBase',
      'dojo/window'
   ],
   function(declare, array, lang, ButtonRow, WidgetBase, winUtils)
   {
      return declare([WidgetBase],
      {
         mNoButtonRow: false,
         mCanceLabel: "Cancel",
         mCancelIconClass: "icons-fugue-icons-16x16-cross-script",
         mSubmitBusyLabel: "Submitting...",
         mSubmitIconClass: "icons-fugue-icons-16x16-disk-black",
         mSubmitLabel: "Submit",
         mEmitted: false,
         postCreate: function()
         {
            this.inherited(arguments);
            
            if(this.mNoButtonRow)
               return;
            
            this.mButtonRow = new ButtonRow({
               mCanceLabel:      this.mCanceLabel,
               mCancelIconClass: this.mCancelIconClass,
               mSubmitBusyLabel: this.mSubmitBusyLabel,
               mSubmitIconClass: this.mSubmitIconClass,
               mSubmitLabel:     this.mSubmitLabel,
               mBack:            false,
               mNext:            false
            }, this.mAttachPointForButtonRow);
            this.mChildWidgets.push(this.mButtonRow);

            this.mButtonRow.on('submit', lang.hitch(this, function(){
               if(!this.validate())
               {
                  this.mButtonRow.reset();
                  return;
               }
               //If there's a form associated with this widget, it will handle the submit.
               //if(this.mForm)
               //   return;
               
               if(this.emitFormExecuted)
               {
                  if(!this.mEmitted)
                     this.mEmitted = this.emitFormExecuted();
               }
               else
               {
                  console.error("Child class of noBusinessBase/form/WidgetFakeForm must implement emitFormExecuted.");
                  this.mButtonRow.reset();
               }
            }));
            
            this.mButtonRow.on('cancel', lang.hitch(this, function(){
               this.emit('formCanceled');
            }));

         },

      //Update from _formMixin on dojo updates
      //
      //
      //
		_getDescendantFormWidgets: function(/*dijit/_WidgetBase[]?*/ children){
			// summary:
			//		Returns all form widget descendants, searching through non-form child widgets like BorderContainer
			var res = [];
			array.forEach(children || this.getChildren(), function(child){
				if("value" in child){
					res.push(child);
				}else{
					res = res.concat(this._getDescendantFormWidgets(child.getChildren()));
				}
			}, this);
			return res;
		},

		reset: function(){
			array.forEach(this._getDescendantFormWidgets(), function(widget){
				if(widget.reset){
					widget.reset();
				}
			});
		},

		validate: function(){
			// summary:
			//		returns if the form is valid - same as isValid - but
			//		provides a few additional (ui-specific) features:
			//
			//		1. it will highlight any sub-widgets that are not valid
			//		2. it will call focus() on the first invalid sub-widget
			var didFocus = false;
			return array.every(array.map(this._getDescendantFormWidgets(), function(widget){
				// Need to set this so that "required" widgets get their
				// state set.
				widget._hasBeenBlurred = true;
				var valid = widget.disabled || !widget.validate || widget.validate();
				if(!valid && !didFocus){
					// Set focus of the first non-valid widget
					winUtils.scrollIntoView(widget.containerNode || widget.domNode);
					widget.focus();
					didFocus = true;
				}
				return valid;
			}), function(item){ return item; });
		}
      
      });
   }
);
